

window.requestAnimFrame =
	window.requestAnimationFrame ||
	window.webkitRequestAnimationFrame ||
	window.mozRequestAnimationFrame ||
	window.oRequestAnimationFrame ||
	window.msRequestAnimationFrame ||
	function(callback) {
		window.setTimeout(callback, 1000 / 30);
	};

// ### 控制整个画布渲染和擦除 ###
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var elements = {};

var gameInfo={
    isOver:false,
    get val(){
        return this.isOver
    },

    set val(newValue){

        if(newValue==true){
            alert("游戏结束")
        }
        this.isOver = newValue
    }
}

monsterList=[]

// 设置个数属性不可遍历
Object.defineProperty(elements,"len",{
    enumerable:false,
    writable:true,
    value:0
})


function Rect({ top, left, width, height, bg = '#333',isover=false ,monstername}) {

	this.width = width;
	this.height = height;
	this.top = top;
	this.left = left;
    this.bg = bg;
    this.isover = isover;

    
    elements.len++

    monstername &&(this.monstername=monstername)

    var name  =this.index = "rect_"+elements.len
    elements[name] =this


}
 
Rect.prototype = {

	draw: function(context) {
		context.fillStyle = this.bg;
		context.fillRect(this.left, this.top, this.width, this.height);
	},

    // 移动
	move: function(direction, num = 10) {

		switch (direction) {
			case 'up':
				this.top -= num;
				break;

			case 'down':
				this.top += num;
				break;

			case 'left':
				this.left -= num;
				break;

			case 'right':
				this.left += num;
				break;
		}


	},

    // 清除模块
	clear: function({ left = 0, top = 0, w = 0, h = 0 ,index} = {}) {

        this.isover=true

        delete elements[this.index]

        // console.log('clear',this.index,elements);

        // elements.len--

		context.clearRect(this.left + left, this.top + top, this.width + w, this.height + h);

	},

    // 碰撞检测
	crashDetection: function(item) {

		var isDetection = false;

		var w = this.width;
		var h = this.height;
		var left = this.left;
		var top = this.top;
		var bottom = top + h;
		var right = left + w;

		// 想要检测的物体
		var d_w = item.width;
		var d_h = item.height;
		var d_left = item.left;
		var d_top = item.top;
		var d_right = d_left + d_w;
		var d_bottom = d_top + d_h;

		//  是否碰撞
		var isLeftD = false,
			isRightD = false,
			isTopD = false,
			isBottomD = false;

		// 我的右边小于 别人左边 left+w <d_left
		// 我的左边大于 别人右边 left > d_left+d_w
		// 我的头 大于 别人的尾  top > d_top+h
		// 我的尾 小于 别人的头  top+h < d_top

		var R = right >= d_left, // 右碰到 左
			L = left <= d_right, // 左碰到 右
			T = top <= d_bottom, // 头碰到了尾
			B = bottom >= d_top; //  尾碰到了头

		// 判断 纵向 是否在对比物体 的 范围内
		var bottom_line_between_ttem = bottom >= d_top && top <= d_bottom;

		// 判断 横向 是否在 对比物体范围内
		var left_line_between_ttem = right >= d_left && left <= d_right;

		// 判断上下是否贴边
		var top_bottom_gule = bottom == d_top || top == d_bottom;

		//  判断左右是否贴边
		var left_right_gule = right == d_left || left == d_right;

		// 是否 右边贴着 对比物
		if (R && left < d_left && bottom_line_between_ttem) {
			// 边界处理，贴边的时候
			if (!(R && top_bottom_gule)) {
				isRightD = true;
			}
		}

		// 是否 左边贴着 对比物
		if (L && right > d_right && bottom_line_between_ttem) {
			if (!(L && top_bottom_gule)) {
				isLeftD = true;
			}
		}

		// 是否 上边贴着 对比物
		if (T && bottom > d_bottom && left_line_between_ttem) {
			if (!(T && left_right_gule)) {
				isTopD = true;
			}
		}

		// 是否 下边贴着 对比物
		if (B && top < d_top && left_line_between_ttem) {
			if (!(B && left_right_gule)) {
				isBottomD = true;
			}
		}

		return {
			isLeftD,
			isRightD,
			isTopD,
			isBottomD,
			isDetection: isLeftD || isRightD || isTopD || isBottomD,
			detectRect: item
		};
    },
    
    getIsDetect:function(item){
        
		var isDetection = false;

		var w = this.width;
		var h = this.height;
		var left = this.left;
		var top = this.top;
		var bottom = top + h;
        var right = left + w;

		// 想要检测的物体
		var d_w = item.width;
		var d_h = item.height;
		var d_left = item.left;
		var d_top = item.top;
		var d_right = d_left + d_w;
		var d_bottom = d_top + d_h;
    
		var R = right < d_left, // 右碰到 左
        L = left > d_right, // 左碰到 右
        T = top > d_bottom, // 头碰到了尾
        B = bottom < d_top; //  尾碰到了头

        if(!R&&!L&&!T&&!B){
            return true
        }

        return false
        
    
    }
};

// 擦除画布函数，可以将整个画布擦除
function clearAll() {
	context.clearRect(0, 0, canvas.width, canvas.height);
}

// 全局 draw 函数，调用所有画布实例的 draw 方法
function draw() {
    
    for (var i in elements) {

        var item = elements[i]
		item.draw(context);
    
    }
}

// 刷新画布，擦除整个画布后重新画
function refresh() {
	clearAll();
	draw();
}


// 生成子弹
function createBullet() { 

	var left = rect1.left;
	var top = rect1.top;
	var w = rect1.width;
	var h = rect1.height;

	var bullet = new Rect({
		left: left + w / 2 - 2,
		top: top - 20,
		width: 4,
		height: 8,
		bg: 'red'
	});


	function bulletMove(params) {

        refresh();
        
        for (var i=0;i< monsterList.length;i++) {

            const element = monsterList[i];

            if(element.isover) continue

            //  判断是否碰撞
            var isdetect = bullet.getIsDetect(element);

            if (isdetect) {
                
                // top 移动了 5px，所以需要加回来
                bullet.clear({ top: 5 });
                beatMonster(element,i)

                return;
            }

            // 如果 子弹飞出屏幕，就停止
            if (bullet.top < -2 * bullet.height || bullet.left < -2 * bullet.width) {
                bullet.clear({ top: 5 });
                return;
            }
            
        }

		bullet.move('up', 5);

    }

    updateCallback.push(bulletMove)
    
}

// 创建一排怪兽
function createRowMonster(params) {

    var left = 50
    var top = 50

    for (let index = 0; index < 5; index++) {

        var monster = new Rect({
            left: left+70*index,
            top: top,
            width: 50,
            height: 50,
            bg: 'black'
        });

        monsterList.push(monster)
        
    }
    
    var direction="right"

    function monsterMove(params) {

        refresh();

        var isDown=false

        if(monsterList.length==0) {
            
            gameInfo.isOver=true
            return

        } 
        
        if(monsterList[0].left<=0) {
            direction="right"
            isDown=true
        }

        else if (monsterList[monsterList.length-1].left>= canvas.width-60){ 
        
            direction="left"
            isDown=true 
        }

        for (var i=0;i< monsterList.length;i++) {

            var monster = monsterList[i]

            if(monster.getIsDetect(rect1)){

                console.log("游戏结束")
                
                gameInfo.isOver=true

                return  
            }

            monster.move(direction,num=0.8 )
            isDown && monster.move("down",num=50)
        
        }
        
    }

    updateCallback.push(monsterMove)

    
}

// 消除怪兽
function beatMonster(item,i) {
    
    item.clear({ index:i });
    monsterList.splice(i,1)

}


//  方向键
document.onkeydown = function(e) {

	var eCode = e.keyCode;
	var left = rect1.left;
	var top = rect1.top;
	var w = rect1.width;
    var h = rect1.height;

    if(gameInfo.isOver) return 

	// left
	if (eCode == 37 && !(left <= 0)) {
        rect1.move("left");
	} else if (eCode == 38 && !(top <= 0)) {
		//up
        rect1.move("up");
	} else if (eCode == 39 && !(left + w >= canvas.width)) {
		//right
        rect1.move("right");
	} else if (eCode == 40 && !(top + h >= canvas.height)) {
		//down
        rect1.move("down");
	} else if (eCode == 32) {
		// 空格 发射
		createBullet();
	}

    refresh();
	// console.log(eCode)
};


// 生成飞机
var rect1 = new Rect({
	left: 50,
	top: 450,
	width: 30,
    height: 30,
    bg:"rgb(249, 242, 244)"
});

var updateCallback=[]

function updateCanvas(params) {

    var result = gameInfo.gameResult;

    if(result =="win" || result=="lose") return 
    
    for (var i = 0, len = updateCallback.length; i < len; i++) {
    
        var item = updateCallback[i]

        item()
    
    }

    requestAnimationFrame(updateCanvas)

}

createRowMonster()

updateCanvas()


draw();
